#include <iostream>
#include <assert.h>

using namespace std;

namespace zch
{
    template<class T>
    class vector{
    public:
        typedef T* iterator;
        typedef const T* const_iterator;
    public:
        iterator begin()
        {
            return _start;
        }

        iterator end()
        {
            return _finish;
        }
        
        const_iterator begin() const
        {
            return _start;
        }

        const_iterator end() const
        {
            return _finish;
        }
    public:
        vector()
        :_start(nullptr)
        ,_finish(nullptr)
        ,_endofstorage(nullptr)
        {
            cout << "默认构造" << endl;
        }   

        template<class InputIterator>
        vector(InputIterator first, InputIterator last)
        :_start(nullptr)
        ,_finish(nullptr)
        ,_endofstorage(nullptr)
        {
            cout << "迭代器构造" << endl;

            for(; first != last; ++first)
            {
                push_back(*first);
            }
        }

        vector(size_t n, const T& val)
        :_start(nullptr)
        ,_finish(nullptr)
        ,_endofstorage(nullptr)
        {
            reserve(n);
            for(int i = 0; i < n; ++i)
            {
                push_back(val);
            }
        }

        vector(long n, const T& val)
        :_start(nullptr)
        ,_finish(nullptr)
        ,_endofstorage(nullptr)
        {
            reserve(n);
            for(int i = 0; i < n; ++i)
            {
                push_back(val);
            }
        }

        vector(int n, const T& val)
        :_start(nullptr)
        ,_finish(nullptr)
        ,_endofstorage(nullptr)
        {
            reserve(n);
            for(int i = 0; i < n; ++i)
            {
                push_back(val);
            }
        }

        vector(const vector<T>& v)
        :_start(nullptr)
        ,_finish(nullptr)
        ,_endofstorage(nullptr)
        {
            cout << "拷贝构造" << endl;

            _start = new T[v.capacity()];
            for(int i = 0; i < v.size(); ++i)
            {
                _start[i] = v[i];
            }
            _finish = _start + v.size();
            _endofstorage = _start + v.capacity();
        }

        vector<T>& operator=(const vector<T>& v)
        {
            if(this != &v) //防止拷贝自己
            {
                delete[] _start;
                _start = new T[v.capacity(0)];
                for(size_t i = 0; i < size(); ++i)
                {
                    _start[i] = v[i];
                } 
                _finish = _start + size();
                _endofstorage = _start + capacity();
            }

            return *this;
        }

        void push_back(const T& val)
        {
            if(_finish == _endofstorage)
            {
                size_t newCapacity = capacity() == 0? 4 : 2 * capacity();
                reserve(newCapacity);
            }
            *_finish = val;
            ++_finish;
        }

        void pop_back()
        {
            assert(!empty());
            --_finish;
        }

        iterator insert(iterator pos, const T& val)
        {
            if(_finish == _endofstorage)
            {
                size_t len = pos - _start;
                size_t newCapacity = capacity() == 0? 4 : 2 * capacity();
                reserve(newCapacity);
                pos = _start + len;
            }

            iterator end = _finish;
            while(end >= pos + 1)
            {
                *end = *(end - 1);
                --end;
            }

            *end = val;
            ++_finish;
        }

        iterator erase(iterator pos)
        {
            assert(!empty());
            for(iterator i = pos; i < _finish - 1; ++i)
            {
                *i = *(i + 1);
            }

            --_finish;
            return pos;
        }

        void reserve(int n)
        {
            if(n > capacity())
            {
                T* start = new T[n];
                size_t sz = size();
                if(_start)
                {
                    for(int i = 0; i < sz; ++i)
                    {
                        start[i] = _start[i];
                    }
                }

                swap(start, _start);
                _finish = _start + sz;
                _endofstorage = _start + n;
                delete[] start;
            }
        }

        void resize(size_t n, const T& val = 0)
        {
            if(n < size())
            {
                _finish = _start + n;
            }
            else
            {
                if(n > capacity())
                {
                    reserve(n);
                }

                while(_finish < _start + n)
                {
                    //push_back(val);
                    *_finish = val;
                    ++_finish;
                }
            }
        }

        size_t capacity() const
        {
            return _endofstorage - _start;
        }

        size_t size() const
        {
            return _finish - _start;
        }

        bool empty() const
        {
            return _start == _finish;
        }

        T& operator[](size_t i) const
        {
            assert(i < size());

            return _start[i];
        }

        // const T& operator[](size_t i) const
        // {
        //     assert(i < size());
        //     return _start[i];
        // }

        ~vector()
        {
            if(_start != nullptr)
            {
                delete[] _start;
                _start = _finish = _endofstorage = nullptr;
            }
        } 
        void print()
        {
            iterator start = _start;
            for(; start != _finish; ++start)
            {
                cout << *start << " ";
            }
            cout << endl;
        }
    private:
        iterator _start;
        iterator _finish;
        iterator _endofstorage;
    };
    
    void test1()
    {
        zch::vector<int> a;
        for(int i = 0; i < 10; ++i)
        {
            a.push_back(i);
        }
        a.print();

        zch::vector<int> b(10, 5);
        b.print();

        a.resize(20);
        b.resize(5);

        a.print();
        b.print();

        vector<int> c;
        c.reserve(20);
        cout << c.size() << " " << c.capacity() << endl;
        if(c.empty())
        {
            cout << "yes" << endl;
        }
        else 
        {
            cout << "no" << endl;
        }

        vector<int> d = a; 
        a.insert(a.begin(), 55);
        b.insert(b.begin() + 5, 55);
        a.erase(a.begin());
        a.print();
        b.print();
        d.print();
    }
}